/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.udt.generator.api.typeprocessers.persistencevaluereader;

import com.inspur.edp.caf.generator.BaseGenerator;
import com.inspur.edp.caf.generator.composite.CompositeGenerator;
import com.inspur.edp.caf.generator.composite.CompositeGeneratorContext;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.element.EnumIndexType;
import com.inspur.edp.cef.repository.typetransprocesser.*;
import com.inspur.edp.udt.designtime.api.entity.ComplexDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.SimpleDataTypeDef;
import com.inspur.edp.udt.designtime.api.entity.element.UdtElement;
import com.inspur.edp.udt.generator.api.UdtApiGenCtx;

import java.util.ArrayList;

public class PersistenceValueReadersGenerator extends CompositeGenerator {
    private UdtApiGenCtx apiGenCtx;

    public PersistenceValueReadersGenerator(UdtApiGenCtx apiGenCtx) {
        this.apiGenCtx = apiGenCtx;
    }

    protected PersistenceValueReadersGenCtx getContext() {
        return (PersistenceValueReadersGenCtx) super.getContext();
    }

    @Override
    protected CompositeGeneratorContext createCompositeContext() {
        return new PersistenceValueReadersGenCtx(apiGenCtx);
    }

    @Override
    protected ArrayList<BaseGenerator> createCompositeItemGenerators() {
        ArrayList<BaseGenerator> list = new java.util.ArrayList<BaseGenerator>();
        if (apiGenCtx.getUdtGenContext().getUdt() instanceof SimpleDataTypeDef) {
            addSimpleUdtTypeProcessorGenertors(list, (SimpleDataTypeDef)
                ((apiGenCtx.getUdtGenContext().getUdt() instanceof SimpleDataTypeDef)
                    ? apiGenCtx.getUdtGenContext().getUdt()
                    : null));
        } else {
            addCompositeUdtTypeProcessGenerators(list, (ComplexDataTypeDef)
                ((apiGenCtx.getUdtGenContext().getUdt() instanceof ComplexDataTypeDef)
                    ? apiGenCtx.getUdtGenContext().getUdt()
                    : null));
        }
        return list;
    }

    private void addSimpleUdtTypeProcessorGenertors(java.util.ArrayList<BaseGenerator> list, SimpleDataTypeDef simpleUdt) {

        String className= simpleUdt.getCode() + "PersistanceValueReader";
        IGspCommonField element = simpleUdt.getContainElements().get(0);
        String lableId = element.getLabelID();

        UdtElement udtElement =(UdtElement) ((element instanceof UdtElement)
            ? element : null);

        switch (simpleUdt.getObjectType()) {
            case None:
                createNormalDataReader(className,
                    list,
                    lableId,
                    udtElement);

                break;
            case Association:
                createAssDataReader(className,
                    list,
                    lableId,
                    udtElement);
                break;
            case Enum:
                createEnumDataReader(className,
                    list,
                    lableId,
                    udtElement);
                break;
        }
    }

    private void createEnumDataReader(String className, ArrayList<BaseGenerator> list, String propertyName, UdtElement udtElement) {
        java.lang.Class processorType;
        switch (udtElement.getMDataType()) {
            case String:
                processorType = Enum2VarcharProcesser.class;
                break;
            case Integer:
                processorType = IntTransProcesser.class;
                break;
            default:
                throw new RuntimeException("不支持枚举设置成数据类型" + String.valueOf(udtElement.getMDataType()) + "，请使用字符串类型或整形");
        }

        UdtGetPersistenceValueMethodGenerator gen;
        if(udtElement.getEnumIndexType()== EnumIndexType.Integer){
             gen= new UdtEnumPersistenceValueGenerator(
                    apiGenCtx.getUdtGenContext(), processorType, propertyName);
        } else{
           gen = new SimpleUdtEnumPersistanceGenerator(
                    apiGenCtx.getUdtGenContext(), processorType, propertyName);
        }
        list.add(new PersistenceValueReaderGenerator(className, getContext(), apiGenCtx, udtElement.getLabelID(), gen, true));

        //UdtGetPersistenceValueMethodGenerator gen
        //   = new UdtEnumPersistenceValueGenerator(apiGenCtx.UdtGenContext, propertyName, udtElement);
        //list.Add(new PersistenceValueReaderGenerator(className, Context, apiGenCtx, udtElement.LabelID, gen));
    }

    private void createAssDataReader(String className, ArrayList<BaseGenerator> list, String propertyName, UdtElement udtElement) {
        UdtGetPersistenceValueMethodGenerator gen =
            new UdtAssPersistenceValueGenerator(
                apiGenCtx.getUdtGenContext(),
                propertyName,
                udtElement);
        list.add(new PersistenceValueReaderGenerator(className, getContext(), apiGenCtx, udtElement.getLabelID(), gen));

    }

    private void createNormalDataReader(String className, java.util.ArrayList<BaseGenerator> list, String propertyName, UdtElement element) {
        Class processorType = null;
        switch (element.getMDataType()) {
            case String:
                processorType = VarcharTransProcesser.class;
                break;
            case Text:
                processorType = ClobTransProcesser.class;
                break;
            case Binary:
                processorType = BinaryTransProcesser.class;
                break;
            case Boolean:
                processorType = Bool2CharProcesser.class;
                break;
            case Integer:
                processorType = IntTransProcesser.class;
                break;
            case Decimal:
                processorType = DecimalTransProcesser.class;
                break;
            case Date:
                processorType = DateTimeTransProcesser.class;
                break;
            case DateTime:
                processorType = DateTimeTransProcesser.class;
                break;
            default:
                throw new RuntimeException();
        }
        UdtGetPersistenceValueMethodGenerator gen = new NullableTransPersistenceValueReaderGenerator(apiGenCtx.getUdtGenContext(), processorType, propertyName);
        list.add(new PersistenceValueReaderGenerator(className, getContext(), apiGenCtx, element.getLabelID(), gen, true));
    }

    private void addCompositeUdtTypeProcessGenerators(java.util.ArrayList<BaseGenerator> list, ComplexDataTypeDef complexUdt) {
        switch (complexUdt.getDbInfo().getMappingType()) {
            case SingleColumn:
                getSingleColumns(list, complexUdt);
                break;
            case MultiColumns:
                getMultiColumns(list, complexUdt);
                break;
            default:
                throw new RuntimeException("不存在类型"+complexUdt.getDbInfo().getMappingType().toString());
        }
    }

    private void getSingleColumns(ArrayList<BaseGenerator> list, ComplexDataTypeDef complexUdt) {
        UdtGetPersistenceValueMethodGenerator gen = new JsonSerializePersistenceValueReadGenerator();
        list.add(new PersistenceValueReaderGenerator(complexUdt.getCode()
            + "PersistanceValueReader", getContext(), apiGenCtx, complexUdt.getCode(), gen));
    }


    private void getMultiColumns(ArrayList<BaseGenerator> list, ComplexDataTypeDef complexUdt) {
        for (IGspCommonField ele : complexUdt.getContainElements()) {
            UdtElement item = (UdtElement)ele;
            if (item.getIsUdt()) {
                createUdtElementDataReader(item, complexUdt, list);
            } else {
                switch (item.getObjectType()) {
                    case None:
                        createNormalDataReader( item.getLabelID()+ "PersistanceValueReader",
                            list, item.getLabelID(), item);
                        break;
                    case Association:
                        createAssDataReader( item.getLabelID()+"PersistanceValueReader",
                            list, item.getLabelID(), item);
                        break;
                    case Enum:
                        createEnumDataReader(item.getLabelID()+ "PersistanceValueReader",
                            list, item.getLabelID(), item);
                        break;
                    default:
                        throw new RuntimeException("不存在類型"+item.getObjectType().toString());
                }
            }
        }
    }

    private void createUdtElementDataReader(UdtElement item, ComplexDataTypeDef complexUdt, java.util.ArrayList<BaseGenerator> list) {
        //TODO: 存为多列时多值嵌套一个单值的场景暂不支持, 变量上需要使用, 屏蔽报错
        //throw new NotImplementedException();
    }
}
